// file: ADC.c
// author: Sebastian Steppeler copyright 2012
/*license: This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/

#include <avr/io.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include "typedefs.h"
#include "ADC.h"


// globals:
volatile char cChan=0;
// externs:
extern volatile char bNewSample;
extern volatile int iSampleExchange[8];
extern volatile int iCounterTest;
extern volatile int8_t cPolarity;

// functions:


// init our ADC
void ADC_Init(void) {
 
	volatile uint16_t result;

	DDRA = 0;
	PORTA = 0;
 
	ADMUX = /*(1<<REFS1) |*/ (1<<REFS0);      // vcc reference
	ADCSRA = (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);  // FCPU / 128 + interrupt enable
	ADCSRA |= (1<<ADEN);
 
	// do a first conversion + read:
	ADCSRA |= (1<<ADSC);
	while (ADCSRA & (1<<ADSC));
	result = ADCW;

	ADCSRA |= (1<<ADIE);

	return;
}
 
// ADC single shot:
uint16_t ADC_Read( uint8_t channel )
{
	// choose channel and start conversion:
	ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
	ADCSRA |= (1<<ADSC);
 
	// wait for conversion finished
	while (ADCSRA & (1<<ADSC));

	// read and return value
	return ADCW;
}

// start AD conversion:
void ADC_StartConversion( uint8_t channel )
{
	// choose channel:
	ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
	// start conversion:
	ADCSRA |= (1<<ADSC);
	
	return;
}



// interrupts:

ISR(ADC_vect)
{	
	volatile short dummyread;

	if(!bNewSample)
	{		
		iSampleExchange[(int)cChan] = ADCW;
		
		if(cPolarity == -1)
			iSampleExchange[(int)cChan] = 1023 - iSampleExchange[(int)cChan];
		
		/*if(cChan == 2)
			iCounterTest = iSampleExchange[(int)cChan];*/
		// debug with random samples:
		/*dummyread = ADCW;
		iSampleExchange[(int)cChan] = rand() % 90;*/
				
		if(cChan == 7)
		{
			cChan = 0;
			bNewSample = true;
		}
		else
			cChan++;		
	}
	else
	{
		// report error:
		/*set_cursor(0,1);
		lcd_string("Sample dropped!");*/
		//sei();
		/*NoteOn(D4, 111);
		NoteOn(F4, 111);
		NoteOn(A4, 111);
		NoteOn(D5, 111);
		_delay_ms(500);
		NoteOff(D4, 127);
		NoteOff(F4, 127);
		NoteOff(A4, 127);
		NoteOff(D5, 127);*/
		
		dummyread = ADCW;		
	}

	ADC_StartConversion(cChan);
	
	//PORTC = 0xff;
	//PORTC = 0;
}
